package com.niodata.dp.app.dao.handler;

import com.niodata.dp.app.AccumulatorValue;
import com.niodata.dp.app.CheckPointValue;
import com.niodata.dp.app.IndicatorValue;
import com.niodata.dp.app.QueueValue;
import com.niodata.dp.app.VariableType;
import com.niodata.dp.app.VariableValue;
import com.niodata.dp.log.LogUtil;
import com.niodata.dp.mybatis.DpMybatisTypeHandler;
import com.niodata.dp.util.JsonUtil;
import java.io.IOException;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import org.apache.ibatis.type.BaseTypeHandler;
import org.apache.ibatis.type.JdbcType;
import org.apache.log4j.Logger;

public class VariableValueTypeHandler extends BaseTypeHandler<VariableValue> implements
      DpMybatisTypeHandler {

  private static final Logger logger = Logger.getLogger(VariableValueTypeHandler.class);

  @Override
  public JdbcType getJdbcType() {
    return JdbcType.LONGVARCHAR;
  }

  @Override
  public Class getTypeHandlerClass() {
    return VariableValueTypeHandler.class;
  }

  @Override
  public Class getJavaClass() {
    return VariableValue.class;
  }

  @Override
  public void setNonNullParameter(PreparedStatement ps, int i, VariableValue parameter,
      JdbcType jdbcType) throws SQLException {
    try {
      String json = JsonUtil.toJson(parameter);
      ps.setString(i, json);
    } catch (IOException e) {
      LogUtil.logStackTrace(logger, e);
    }
  }

  @Override
  public VariableValue getNullableResult(ResultSet rs, String columnName) throws SQLException {
    String json = rs.getString(columnName);
    if (json == null || json.length() == 0) {
      return null;
    }
    try {
      String type = rs.getString("TYPE");
      VariableType variableType = VariableType.valueOf(type);
      switch (variableType) {
        case Indicator:
          return JsonUtil.fromJson(IndicatorValue.class, json);
        case Accumulator:
          return JsonUtil.fromJson(AccumulatorValue.class, json);
        case Queue:
          return JsonUtil.fromJson(QueueValue.class, json);
        case CheckPoint:
          return JsonUtil.fromJson(CheckPointValue.class, json);
        default:
          return null;
      }

    } catch (IOException e) {
      LogUtil.logStackTrace(logger, e);
    }

    return null;
  }

  @Override
  public VariableValue getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
    String json = rs.getString(columnIndex);
    if (json == null || json.length() == 0) {
      return null;
    }
    try {
      String type = rs.getString("TYPE");
      VariableType variableType = VariableType.valueOf(type);

      switch (variableType) {
        case Indicator:
          return JsonUtil.fromJson(IndicatorValue.class, json);
        case Accumulator:
          return JsonUtil.fromJson(AccumulatorValue.class, json);
        case Queue:
          return JsonUtil.fromJson(QueueValue.class, json);
        case CheckPoint:
          return JsonUtil.fromJson(CheckPointValue.class, json);
        default:
          return null;
      }

    } catch (IOException e) {
      LogUtil.logStackTrace(logger, e);
    }

    return null;
  }

  @Override
  public VariableValue getNullableResult(CallableStatement cs, int columnIndex)
      throws SQLException {
    return null;
  }
}
